using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
//cubeMesh
[RequireComponent(typeof(MeshFilter ),typeof(MeshRenderer))]
[ExecuteInEditMode]
public class cubeMesh : MonoBehaviour
{
    public Vector3 center = Vector3.zero;
    public float radius = 0.1f;
    public int xSize=4,ySize=5, zSize=3;
    public int roundness=2;
    // Start is called before the first frame update
    private Vector3[]vertices;
    private Vector3[] normals;
    private Mesh mymesh;
    
    private void Awake () 
    {
        Generate();
        
    }
    private void CreateVertices () {
		int cornerVertices = 8;
		int edgeVertices = (xSize + ySize + zSize - 3) * 4;
		int faceVertices = (
			(xSize - 1) * (ySize - 1) +
			(xSize - 1) * (zSize - 1) +
			(ySize - 1) * (zSize - 1)) * 2;
		vertices = new Vector3[cornerVertices + edgeVertices + faceVertices];
        normals = new Vector3[vertices.Length];

        int v=0;
		for (int y = 0; y <= ySize; y++) 
        {
			for (int x = 0; x <= xSize; x++) 
            {
                SetVertex(v++,x,y,0);
				
			}
			for (int z = 1; z <= zSize; z++) 
            {
				
                SetVertex(v++,xSize, y, z);
			}
			for (int x = xSize - 1; x >= 0; x--) 
            {
                SetVertex(v++,x, y, zSize);
				
			}
			for (int z = zSize - 1; z > 0; z--) 
            {
                SetVertex(v++,0, y, z);
			}
		}
        for (int z = 1; z < zSize; z++) 
        {
			for (int x = 1; x < xSize; x++) 
            {
                SetVertex(v++,x, ySize, z);
			}
		}
		for (int z = 1; z < zSize; z++) 
        {
			for (int x = 1; x < xSize; x++) 
            {
                SetVertex(v++,x, 0, z);
				
			}
		}

        mymesh.vertices=vertices;
        mymesh.normals=normals;
	}
    private int CreateBottomFace (int[] triangles, int t, int ring) 
    {
		int v = 1;
		int vMid = vertices.Length - (xSize - 1) * (zSize - 1);
		t = SetQuad(triangles, t, ring - 1, vMid, 0, 1);
		for (int x = 1; x < xSize - 1; x++, v++, vMid++) {
			t = SetQuad(triangles, t, vMid, vMid + 1, v, v + 1);
		}
		t = SetQuad(triangles, t, vMid, v + 2, v, v + 1);

		int vMin = ring - 2;
		vMid -= xSize - 2;
		int vMax = v + 2;

		for (int z = 1; z < zSize - 1; z++, vMin--, vMid++, vMax++) {
			t = SetQuad(triangles, t, vMin, vMid + xSize - 1, vMin + 1, vMid);
			for (int x = 1; x < xSize - 1; x++, vMid++) {
				t = SetQuad(
					triangles, t,
					vMid + xSize - 1, vMid + xSize, vMid, vMid + 1);
			}
			t = SetQuad(triangles, t, vMid + xSize - 1, vMax + 1, vMid, vMax);
		}

		int vTop = vMin - 1;
		t = SetQuad(triangles, t, vTop + 1, vTop, vTop + 2, vMid);
		for (int x = 1; x < xSize - 1; x++, vTop--, vMid++) {
			t = SetQuad(triangles, t, vTop, vTop - 1, vMid, vMid + 1);
		}
		t = SetQuad(triangles, t, vTop, vTop - 1, vMid, vTop - 2);
		
		return t;
	}

    private int CreateTopFace (int[] triangles, int t, int ring) 
    {
		int v = ring * ySize;
		for (int x = 0; x < xSize - 1; x++, v++) {
			t = SetQuad(triangles, t, v, v + 1, v + ring - 1, v + ring);
		}
		t = SetQuad(triangles, t, v, v + 1, v + ring - 1, v + 2);

		int vMin = ring * (ySize + 1) - 1;
		int vMid = vMin + 1;
		int vMax = v + 2;

		for (int z = 1; z < zSize - 1; z++, vMin--, vMid++, vMax++) {
			t = SetQuad(triangles, t, vMin, vMid, vMin - 1, vMid + xSize - 1);
			for (int x = 1; x < xSize - 1; x++, vMid++) {
				t = SetQuad(
					triangles, t,
					vMid, vMid + 1, vMid + xSize - 1, vMid + xSize);
			}
			t = SetQuad(triangles, t, vMid, vMax, vMid + xSize - 1, vMax + 1);
		}

		int vTop = vMin - 2;
		t = SetQuad(triangles, t, vMin, vMid, vTop + 1, vTop);
		for (int x = 1; x < xSize - 1; x++, vTop--, vMid++) {
			t = SetQuad(triangles, t, vMid, vMid + 1, vTop, vTop - 1);
		}
		t = SetQuad(triangles, t, vMid, vTop - 2, vTop, vTop - 1);
        return t;
	}

    private void CreateTriangles () 
    {
        int quads = (xSize * ySize + xSize * zSize + ySize * zSize) * 2;
		// int[] triangles = new int[quads * 6];
        int[] trianglesZ = new int[(xSize * ySize) * 12];
		int[] trianglesX = new int[(ySize * zSize) * 12];
		int[] trianglesY = new int[(xSize * zSize) * 12];
        int ring = (xSize + zSize) * 2;
		int tZ = 0, tX = 0, tY = 0, v = 0;
		

		for (int y = 0; y < ySize; y++, v++) 
        {
			for (int q = 0; q < xSize; q++, v++) {
				tZ = SetQuad(trianglesZ, tZ, v, v + 1, v + ring, v + ring + 1);
			}
			for (int q = 0; q < zSize; q++, v++) {
				tX = SetQuad(trianglesX, tX, v, v + 1, v + ring, v + ring + 1);
			}
			for (int q = 0; q < xSize; q++, v++) {
				tZ = SetQuad(trianglesZ, tZ, v, v + 1, v + ring, v + ring + 1);
			}
			for (int q = 0; q < zSize - 1; q++, v++) {
				tX = SetQuad(trianglesX, tX, v, v + 1, v + ring, v + ring + 1);
			}
			tX = SetQuad(trianglesX, tX, v, v - ring + 1, v + ring, v + 1);
		}
        tY = CreateTopFace(trianglesY, tY, ring);
		tY = CreateBottomFace(trianglesY, tY, ring);
        mymesh.subMeshCount = 3;
		mymesh.SetTriangles(trianglesZ, 0);
		mymesh.SetTriangles(trianglesX, 1);
		mymesh.SetTriangles(trianglesY, 2);

		
	}
    private static int
	SetQuad (int[] triangles, int i, int v00, int v10, int v01, int v11) {
		triangles[i] = v00;
		triangles[i + 1] = triangles[i + 4] = v01;
		triangles[i + 2] = triangles[i + 3] = v10;
		triangles[i + 5] = v11;
		return i + 6;
	}
    private void Generate () {
        GetComponent<MeshFilter>().mesh=mymesh=new Mesh();
        mymesh.name="Procedural Cude";
        CreateVertices();
        CreateTriangles();
        // Vector2[] uv = new Vector2[vertices.Length];
        // Vector4[]tangents=new Vector4[vertices.Length];
        // Vector4 tangent=new Vector4(1f,0f,0f,-1f);
		// for (int i = 0, y = 0; y <= ySize; y++) {
		// 	for (int x = 0; x <= xSize; x++, i++) {
		// 		vertices[i] = new Vector3(x, y);
		// 		uv[i] = new Vector2((float)x / xSize, (float)y / ySize);
        //         tangents[i]=tangent;
		// 	}
		// }
        // mymesh.vertices=vertices;
        // mymesh.uv = uv;
        // mymesh.tangents=tangents;
        // int []triangles =new int [xSize*6*ySize];
       
        // for (int ti = 0, vi = 0, y = 0; y < ySize; y++, vi++) {
		// 	for (int x = 0; x < xSize; x++, ti += 6, vi++) {
		// 		triangles[ti] = vi;
		// 		triangles[ti + 3] = triangles[ti + 2] = vi + 1;
		// 		triangles[ti + 4] = triangles[ti + 1] = vi + xSize + 1;
		// 		triangles[ti + 5] = vi + xSize + 2;
        //         mymesh.triangles=triangles;
        //         yield return wait;
		// 	}
            

		// }
        // mymesh.RecalculateNormals();
        
		
		
        
        

	}
    private void SetVertex (int i, int x, int y, int z) 
    {
		Vector3 inner = vertices[i] = new Vector3(x, y, z);

		if (x < roundness) {
			inner.x = roundness;
		}
		else if (x > xSize - roundness) {
			inner.x = xSize - roundness;
		}
        if (y < roundness) {
			inner.y = roundness;
		}
		else if (y > ySize - roundness) {
			inner.y = ySize - roundness;
		}
        if (z < roundness) {
			inner.z = roundness;
		}
		else if (z > zSize - roundness) {
			inner.z = zSize - roundness;
		}
		normals[i] = (vertices[i] - inner).normalized;
		vertices[i] = inner + normals[i] * roundness;
	}
   


    private void OnDrawGizmos() 
    {
       
        
        if (vertices == null)
		{
			return;
		}
		
		for (int i = 0; i < vertices.Length; i++)
		{
            Gizmos.color = Color.red;
			Gizmos.DrawSphere(vertices[i], 0.1f);
			
			Gizmos.color = Color.yellow;
			Gizmos.DrawRay(vertices[i], normals[i]);
		}
                
        // Vector3 vec=new Vector3(0.01f,0.02f);
        // Gizmos.DrawSphere(transform.position,0.01f);
        // Gizmos.DrawWireSphere(transform.position,0.01f*1.5f);
        // Gizmos.DrawSphere(transform.position+vec,0.01f);
        // Debug.Log(transform.position);   
                

            
            
            
            
            
        
    }
    
    void Update()
    {  
    }
   


    // Update is called once per frame
}
